from django.shortcuts import render, redirect, get_object_or_404
from django.views import View
from django.utils import timezone
from .models import Sensor, MonitoringData, AlertLog, Project, Announcement, Gateway
from django.db.models import Count
from django.contrib.sessions.models import Session

def index(request):
    return render(request, 'index.html')

def map_view(request):
    return render(request, 'map-view.html')

def status_overview(request):
    if request.resolver_match.url_name == 'stress-overview':
        return render(request, 'status-overview.html', {'title': '应力监测概览', 'data_type': 'stress'})
    elif request.resolver_match.url_name == 'displacement-overview':
        return render(request, 'status-overview.html', {'title': '位移监测概览', 'data_type': 'displacement'})
    return render(request, 'status-overview.html')
from django.views.generic import ListView, CreateView, UpdateView, DetailView, DeleteView, TemplateView
from django.views.generic.edit import FormView
from django.urls import reverse_lazy
from django.http import HttpResponse
from django.contrib import messages
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
import pandas as pd
from io import BytesIO
from datetime import datetime
from .models import News, Announcement, User, AlertLog
from .forms import AlertLogForm

class NewsListView(ListView):
    model = News
    template_name = 'news_list.html'
    context_object_name = 'news_list'
    
class NewsCreateView(CreateView):
    model = News
    fields = ['title', 'content', 'category', 'is_published']
    template_name = 'news_form.html'
    success_url = reverse_lazy('news-list')
    
class NewsUpdateView(UpdateView):
    model = News
    fields = ['title', 'content', 'category', 'is_published']
    template_name = 'news_form.html'
    success_url = reverse_lazy('news-list')
    
class NewsDeleteView(DeleteView):
    model = News
    template_name = 'news_confirm_delete.html'
    success_url = reverse_lazy('news-list')
    
class AnnouncementListView(ListView):
    model = Announcement
    template_name = 'announcement_list.html'
    context_object_name = 'announcement_list'
    
class AnnouncementCreateView(CreateView):
    model = Announcement
    fields = ['title', 'content', 'category', 'is_published']
    template_name = 'announcement_form.html'
    success_url = reverse_lazy('announcement-list')
    
class AnnouncementUpdateView(UpdateView):
    model = Announcement
    fields = ['title', 'content', 'category', 'is_published']
    template_name = 'announcement_form.html'
    success_url = reverse_lazy('announcement-list')
    
class AnnouncementDeleteView(DeleteView):
    model = Announcement
    template_name = 'announcement_confirm_delete.html'
    success_url = reverse_lazy('announcement-list')

class UserListView(LoginRequiredMixin, ListView):
    model = User
    template_name = 'user_list.html'
    context_object_name = 'users'
    paginate_by = 20

    def get_queryset(self):
        queryset = super().get_queryset()
        if not self.request.user.is_superuser:
            if self.request.user.role == 'admin':
                queryset = queryset.filter(role='operator')
            else:
                queryset = queryset.none()
        return queryset

class UserCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
    model = User
    fields = ['username', 'password', 'role', 'phone', 'department', 'managed_projects']
    template_name = 'user_form.html'
    success_url = reverse_lazy('user-list')

    def test_func(self):
        return self.request.user.is_superuser or self.request.user.role == 'admin'

    def form_valid(self, form):
        user = form.save(commit=False)
        user.set_password(form.cleaned_data['password'])
        user.save()
        form.save_m2m()
        messages.success(self.request, '用户创建成功')
        return super().form_valid(form)

class UserUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = User
    fields = ['username', 'role', 'phone', 'department', 'managed_projects']
    template_name = 'user_form.html'
    success_url = reverse_lazy('user-list')

    def test_func(self):
        user = self.get_object()
        return (self.request.user.is_superuser or 
                (self.request.user.role == 'admin' and user.role == 'operator') or
                self.request.user == user)

class UserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = User
    template_name = 'user_confirm_delete.html'
    success_url = reverse_lazy('user-list')

    def test_func(self):
        user = self.get_object()
        return self.request.user.is_superuser or (self.request.user.role == 'admin' and user.role == 'operator')

class UserImportExportView(LoginRequiredMixin, UserPassesTestMixin, FormView):
    template_name = 'user_import_export.html'
    success_url = reverse_lazy('user-list')

    def test_func(self):
        return self.request.user.is_superuser or self.request.user.role == 'admin'

    def post(self, request, *args, **kwargs):
        if 'import' in request.FILES:
            return self.import_users(request)
        else:
            return self.export_users()

    def import_users(self, request):
        try:
            df = pd.read_excel(request.FILES['import'])
            # 处理导入逻辑
            messages.success(request, '用户导入成功')
        except Exception as e:
            messages.error(request, f'导入失败: {str(e)}')
        return redirect('user-list')

    def export_users(self):
        queryset = User.objects.all()
        if not self.request.user.is_superuser:
            queryset = queryset.filter(role='operator')
        
        data = [{
            '用户名': user.username,
            '角色': user.get_role_display(),
            '部门': user.department,
            '电话': user.phone
        } for user in queryset]
        
        df = pd.DataFrame(data)
        output = BytesIO()
        writer = pd.ExcelWriter(output, engine='xlsxwriter')
        df.to_excel(writer, index=False, sheet_name='用户列表')
        writer.close()
        output.seek(0)
        
        response = HttpResponse(
            output.getvalue(),
            content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        response['Content-Disposition'] = 'attachment; filename=users_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
        return response

class SensorImportExportView(LoginRequiredMixin, UserPassesTestMixin, FormView):
    template_name = 'sensor_import_export.html'
    success_url = reverse_lazy('sensor-list')

    def test_func(self):
        return self.request.user.is_superuser or self.request.user.role == 'admin'

    def get_form_class(self):
        from django import forms
        return forms.Form

    def post(self, request, *args, **kwargs):
        if 'import' in request.FILES:
            return self.import_sensors(request)
        else:
            return self.export_sensors()

    def import_sensors(self, request):
        try:
            df = pd.read_excel(request.FILES['import'])
            # 处理传感器导入逻辑
            messages.success(request, '传感器导入成功')
        except Exception as e:
            messages.error(request, f'导入失败: {str(e)}')
        return redirect('sensor-list')

    def form_valid(self, form):
        return super().form_valid(form)
        
    def export_sensors(self):
        queryset = Sensor.objects.all()
        
        data = [{
            '传感器名称': sensor.name,
            '设计编号': sensor.design_code,
            '所在位置': sensor.location,
            '传感器类型': sensor.get_sensor_type_display(),
            '状态': sensor.get_status_display()
        } for sensor in queryset]
        
        df = pd.DataFrame(data)
        output = BytesIO()
        writer = pd.ExcelWriter(output, engine='xlsxwriter')
        df.to_excel(writer, index=False, sheet_name='传感器列表')
        writer.close()
        output.seek(0)
        
        response = HttpResponse(
            output.getvalue(),
            content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        response['Content-Disposition'] = 'attachment; filename=sensors_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
        return response

class AlertLogListView(ListView, FormView):
    model = AlertLog
    template_name = 'alert_log_list.html'
    context_object_name = 'alerts'
    paginate_by = 20
    form_class = AlertLogForm
    success_url = reverse_lazy('alert-list')

    def get_queryset(self):
        queryset = super().get_queryset()
        search = self.request.GET.get('search')
        status = self.request.GET.get('status')
        severity = self.request.GET.get('severity')
        
        if search:
            queryset = queryset.filter(
                Q(sensor__name__icontains=search) |
                Q(rule__name__icontains=search) |
                Q(notes__icontains=search)
            )
        if status:
            queryset = queryset.filter(status=status)
        if severity:
            queryset = queryset.filter(severity=severity)
            
        return queryset

    def form_valid(self, form):
        alert = form.save(commit=False)
        alert.resolved_by = self.request.user
        alert.resolved_at = datetime.now()
        alert.save()
        messages.success(self.request, '预警处理信息已保存')
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['status_choices'] = AlertLog.STATUS_CHOICES
        context['severity_choices'] = AlertLog.SEVERITY_CHOICES
        return context

    def get(self, request, *args, **kwargs):
        if 'export' in request.GET:
            return self.export_alerts()
        return super().get(request, *args, **kwargs)

    def export_alerts(self):
        queryset = self.get_queryset()
        data = []
        for alert in queryset:
            data.append({
                '传感器': alert.sensor.name,
                '规则': alert.rule.name,
                '时间戳': alert.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                '严重程度': alert.get_severity_display(),
                '监测值': alert.value,
                '处理状态': alert.get_status_display(),
                '处理备注': alert.notes or '',
                '解决人': alert.resolved_by.username if alert.resolved_by else '',
                '解决时间': alert.resolved_at.strftime('%Y-%m-%d %H:%M:%S') if alert.resolved_at else ''
            })
        
        df = pd.DataFrame(data)
        output = BytesIO()
        writer = pd.ExcelWriter(output, engine='xlsxwriter')
        df.to_excel(writer, index=False, sheet_name='预警信息')
        writer.close()
        output.seek(0)
        
        response = HttpResponse(
            output.getvalue(),
            content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        response['Content-Disposition'] = 'attachment; filename=alert_logs_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
        return response
from django.urls import reverse_lazy
from django.http import JsonResponse, HttpResponse
from .models import Sensor, MonitoringData, Building, Project
import json
import pandas as pd
from io import BytesIO
from datetime import timedelta

class DataVisualizationView(View):
    def get(self, request, parameter=None):
        if parameter is None:
            parameter = request.GET.get('parameter', 'stress')
            
        sensors = Sensor.objects.all()
        parameter_map = {
            'stress': '应力',
            'displacement': '位移',
            'seepage': '渗流',
            'temperature': '温度'
        }
        
        context = {
            'title': f'{parameter_map[parameter]}数据可视化',
            'parameter_name': parameter_map[parameter],
            'parameter_unit': self.get_parameter_unit(parameter),
            'sensors': sensors
        }
        return render(request, 'data_visualization.html', context)
    
    def get_parameter_unit(self, parameter):
        units = {
            'stress': 'kPa',
            'displacement': 'mm',
            'seepage': 'L/s',
            'temperature': '°C'
        }
        return units.get(parameter, '')

class BuildingDetailView(DetailView):
    model = Building
    template_name = 'building_detail.html'

class SectionUpdateView(UpdateView):
    model = Building
    fields = ['section', 'section_details']
    template_name = 'section_form.html'
    success_url = reverse_lazy('building-list')

    def get_object(self):
        return get_object_or_404(Building, pk=self.kwargs['pk'])

class SensorCreateView(CreateView):
    model = Sensor
    fields = ['name', 'location', 'latitude', 'longitude', 'sensor_type', 'installation_date']
    template_name = 'sensor_form.html'

    def get_success_url(self):
        return reverse_lazy('building-detail', kwargs={'pk': self.kwargs['building_pk']})

    def form_valid(self, form):
        building = get_object_or_404(Building, pk=self.kwargs['building_pk'])
        form.instance.building = building
        return super().form_valid(form)

class SensorDetailView(DetailView):
    model = Sensor
    template_name = 'sensor_detail.html'

class SensorUpdateView(UpdateView):
    model = Sensor
    fields = ['name', 'location', 'latitude', 'longitude', 'sensor_type', 'installation_date']
    template_name = 'sensor_form.html'

    def get_success_url(self):
        return reverse_lazy('building-detail', kwargs={'pk': self.object.building.pk})

class SensorDeleteView(DeleteView):
    model = Sensor
    template_name = 'sensor_confirm_delete.html'

    def get_success_url(self):
        return reverse_lazy('building-detail', kwargs={'pk': self.object.building.pk})

class SensorListView(ListView):
    model = Sensor
    template_name = 'sensor_list.html'
    context_object_name = 'sensors'
    paginate_by = 20

    def get_queryset(self):
        queryset = super().get_queryset()
        if not self.request.user.is_superuser:
            if self.request.user.role == 'admin':
                queryset = queryset.filter(role='operator')
            else:
                queryset = queryset.none()
        return queryset

    def form_valid(self, form):
        building = get_object_or_404(Building, pk=self.kwargs['building_pk'])
        form.instance.building = building
        return super().form_valid(form)

class SensorDetailView(DetailView):
    model = Sensor
    template_name = 'sensor_detail.html'

class SensorUpdateView(UpdateView):
    model = Sensor
    fields = ['name', 'location', 'latitude', 'longitude', 'sensor_type', 'installation_date']
    template_name = 'sensor_form.html'

    def get_success_url(self):
        return reverse_lazy('building-detail', kwargs={'pk': self.object.building.pk})

class SensorDeleteView(DeleteView):
    model = Sensor
    template_name = 'sensor_confirm_delete.html'

    def get_success_url(self):
        return reverse_lazy('building-detail', kwargs={'pk': self.object.building.pk})

def dashboard(request):
    """
    监测总览页面 - 集成地图看板和传感器状态
    """
    sensors = Sensor.objects.all()
    sensor_data = [{
        'id': sensor.id,
        'name': sensor.name,
        'location': sensor.location,
        'lat': sensor.latitude,
        'lng': sensor.longitude,
        'status': sensor.status,
        'type': sensor.sensor_type
    } for sensor in sensors]
    
    return render(request, 'dashboard.html', {
        'sensors': json.dumps(sensor_data)
    })

def sensor_data(request, sensor_id):
    """
    获取单个传感器的监测数据(JSON格式)
    """
    data = MonitoringData.objects.filter(sensor_id=sensor_id).order_by('-timestamp')[:100]
    result = [{
        'timestamp': item.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
        'stress': item.stress,
        'displacement': item.displacement,
        'seepage': item.seepage
    } for item in data]
    
    return JsonResponse(result, safe=False)

def compare_data(request):
    """
    历史数据对比分析接口
    """
    sensor_id = request.GET.get('sensor_id')
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    
    if not all([sensor_id, start_date, end_date]):
        return JsonResponse({'error': '缺少必要参数'}, status=400)
    
    try:
        start_date = datetime.strptime(start_date, '%Y-%m-%d')
        end_date = datetime.strptime(end_date, '%Y-%m-%d')
        
        data = MonitoringData.objects.filter(
            sensor_id=sensor_id,
            timestamp__gte=start_date,
            timestamp__lte=end_date
        ).order_by('timestamp')
        
        result = [{
            'timestamp': item.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
            'stress': item.stress,
            'displacement': item.displacement,
            'seepage': item.seepage
        } for item in data]
        
        return JsonResponse(result, safe=False)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

def realtime_data(request):
    """
    实时数据查询接口
    """
    sensor_id = request.GET.get('sensor_id')
    if not sensor_id:
        return JsonResponse({'error': '缺少传感器ID参数'}, status=400)
    
    try:
        # 获取最近30分钟的实时数据
        thirty_min_ago = datetime.now() - timedelta(minutes=30)
        data = MonitoringData.objects.filter(
            sensor_id=sensor_id,
            timestamp__gte=thirty_min_ago
        ).order_by('timestamp')
        
        result = [{
            'timestamp': item.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
            'stress': item.stress,
            'displacement': item.displacement,
            'seepage': item.seepage
        } for item in data]
        
        return JsonResponse(result, safe=False)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)
        
class GatewayListView(ListView):
    model = Gateway
    template_name = 'gateway_list.html'
    context_object_name = 'gateways'
    paginate_by = 20

    def get_queryset(self):
        queryset = super().get_queryset()
        search = self.request.GET.get('search')
        status = self.request.GET.get('status')
        severity = self.request.GET.get('severity')
        
        if search:
            queryset = queryset.filter(
                Q(sensor__name__icontains=search) |
                Q(rule__name__icontains=search) |
                Q(notes__icontains=search)
            )
        if status:
            queryset = queryset.filter(status=status)
        if severity:
            queryset = queryset.filter(severity=severity)
            
        return queryset

    def form_valid(self, form):
        alert = form.save(commit=False)
        alert.resolved_by = self.request.user
        alert.resolved_at = datetime.now()
        alert.save()
        messages.success(self.request, '预警处理信息已保存')
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['status_choices'] = AlertLog.STATUS_CHOICES
        context['severity_choices'] = AlertLog.SEVERITY_CHOICES
        return context

    def get(self, request, *args, **kwargs):
        if 'export' in request.GET:
            return self.export_alerts()
        return super().get(request, *args, **kwargs)

    def export_alerts(self):
        queryset = self.get_queryset()
        data = []
        for alert in queryset:
            data.append({
                '传感器': alert.sensor.name,
                '规则': alert.rule.name,
                '时间戳': alert.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                '严重程度': alert.get_severity_display(),
                '监测值': alert.value,
                '处理状态': alert.get_status_display(),
                '处理备注': alert.notes or '',
                '解决人': alert.resolved_by.username if alert.resolved_by else '',
                '解决时间': alert.resolved_at.strftime('%Y-%m-%d %H:%M:%S') if alert.resolved_at else ''
            })
        
        df = pd.DataFrame(data)
        output = BytesIO()
        writer = pd.ExcelWriter(output, engine='xlsxwriter')
        df.to_excel(writer, index=False, sheet_name='预警信息')
        writer.close()
        output.seek(0)
        
        response = HttpResponse(
            output.getvalue(),
            content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        )
        response['Content-Disposition'] = 'attachment; filename=alert_logs_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
        return response

def export_data(request):
    """
    数据导出接口
    """
    sensor_id = request.GET.get('sensor_id')
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    export_type = request.GET.get('export_type', 'excel')
    
    if not all([sensor_id, start_date, end_date]):
        return JsonResponse({'error': '缺少必要参数'}, status=400)
    
    try:
        start_date = datetime.strptime(start_date, '%Y-%m-%d')
        end_date = datetime.strptime(end_date, '%Y-%m-%d')
        
        data = MonitoringData.objects.filter(
            sensor_id=sensor_id,
            timestamp__gte=start_date,
            timestamp__lte=end_date
        ).order_by('timestamp')
        
        result = [{
            '时间戳': item.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
            '应力值': item.stress,
            '位移量': item.displacement,
            '渗流量': item.seepage
        } for item in data]
        
        if export_type == 'excel':
            df = pd.DataFrame(result)
            output = BytesIO()
            writer = pd.ExcelWriter(output, engine='xlsxwriter')
            df.to_excel(writer, index=False, sheet_name='监测数据')
            writer.close()
            output.seek(0)
            
            response = HttpResponse(
                output.getvalue(),
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            response['Content-Disposition'] = 'attachment; filename=monitoring_data_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
            return response
        else:
            return JsonResponse(result, safe=False)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)

class MaintenanceView(TemplateView):
    template_name = 'maintenance.html'

def export_data(request):
    """
    数据导出接口
    """
    sensor_id = request.GET.get('sensor_id')
    start_date = request.GET.get('start_date')
    end_date = request.GET.get('end_date')
    export_type = request.GET.get('export_type', 'excel')
    
    if not all([sensor_id, start_date, end_date]):
        return JsonResponse({'error': '缺少必要参数'}, status=400)
    
    try:
        start_date = datetime.strptime(start_date, '%Y-%m-%d')
        end_date = datetime.strptime(end_date, '%Y-%m-%d')
        
        data = MonitoringData.objects.filter(
            sensor_id=sensor_id,
            timestamp__gte=start_date,
            timestamp__lte=end_date
        ).order_by('timestamp')
        
        result = [{
            '时间戳': item.timestamp.strftime('%Y-%m-%d %H:%M:%S'),
            '应力值': item.stress,
            '位移量': item.displacement,
            '渗流量': item.seepage
        } for item in data]
        
        if export_type == 'excel':
            df = pd.DataFrame(result)
            output = BytesIO()
            writer = pd.ExcelWriter(output, engine='xlsxwriter')
            df.to_excel(writer, index=False, sheet_name='监测数据')
            writer.close()
            output.seek(0)
            
            response = HttpResponse(
                output.getvalue(),
                content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            )
            response['Content-Disposition'] = 'attachment; filename=monitoring_data_%s.xlsx' % datetime.now().strftime('%Y%m%d%H%M%S')
            return response
        else:
            return JsonResponse(result, safe=False)
    except Exception as e:
        return JsonResponse({'error': str(e)}, status=500)
